package com.wg.core.controller;

import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.wg.core.annotation.Controller;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 控制器管理器，负责控制器的注册、初始化、启动和关闭
 *
 * @author 少爷123
 */
public class ControllerMgr {
    private static final Log log = LogFactory.get();
    private final Map<String, IController> controllerMap = new ConcurrentHashMap<>(32);
    private volatile boolean initialized = false;

    private ControllerMgr() {
    }

    /**
     * 获取单例实例
     *
     * @return ControllerMgr实例
     */
    public static ControllerMgr getInstance() {
        return SingletonHolder.INSTANCE;
    }

    /**
     * 获取所有控制器
     *
     * @return 控制器列表
     */
    public List<IController> getControllers() {
        return new ArrayList<>(controllerMap.values());
    }

    /**
     * 根据类型获取控制器
     *
     * @param clazz 控制器类型
     * @param <T>   泛型类型
     * @return 控制器实例
     */
    @SuppressWarnings("unchecked")
    public <T extends IController> T getController(Class<T> clazz) {
        if (clazz == null) {
            return null;
        }
        return (T) controllerMap.get(clazz.getName());
    }

    /**
     * 根据名称获取控制器
     *
     * @param name 控制器名称
     * @return 控制器实例
     */
    public IController getController(String name) {
        if (name == null || name.isEmpty()) {
            return null;
        }
        return controllerMap.values().stream()
                .filter(controller -> name.equals(controller.getName()))
                .findFirst()
                .orElse(null);
    }

    /**
     * Initialize controller
     *
     * @param packageName Package name
     */
    public void init(String packageName) {
        if (initialized) {
            log.warn("Controller manager has already been initialized");
            return;
        }

        log.info("Start initializing controller, scanning package: {}", packageName);
        try {
            initControllers(packageName);
            initialized = true;
            log.info("Controller initialization completed, loaded {} controllers", controllerMap.size());
        } catch (Exception e) {
            log.error("Failed to initialize controller", e);
        }
    }

    /**
     * 启动所有控制器
     */
    public void startAll() {
        if (!initialized) {
            log.error("Controller manager has not been initialized, cannot start");
            return;
        }

        log.info("Start initializing all controllers");
        int successCount = 0;
        int failCount = 0;

        for (IController controller : controllerMap.values()) {
            try {
                controller.init();
                controller.start();
                successCount++;
            } catch (Exception e) {
                failCount++;
                log.error("Failed to start controller {}", controller.getName(), e);
            }
        }

        log.info("Controller initialization completed: success {}, fail {}", successCount, failCount);
    }

    /**
     * 关闭所有控制器
     */
    public void shutdownAll() {
        log.info("Start shutting down all controllers");
        int successCount = 0;
        int failCount = 0;

        for (IController controller : controllerMap.values()) {
            try {
                controller.shutdown();
                successCount++;
            } catch (Exception e) {
                failCount++;
                log.error("Failed to shutdown controller {}", controller.getName(), e);
            }
        }

        log.info("Controller shutdown completed: success {}, fail {}", successCount, failCount);
    }

    /**
     * 获取控制器数量
     *
     * @return 控制器数量
     */
    public int getControllerCount() {
        return controllerMap.size();
    }

    /**
     * 初始化控制器
     *
     * @param packageName 包名
     */
    private void initControllers(String packageName) {
        Set<Class<?>> classes = ClassUtil.scanPackageByAnnotation(packageName, Controller.class);
        log.info("Found {} classes with @Controller annotation", classes.size());

        for (Class<?> clazz : classes) {
            try {
                if (!IController.class.isAssignableFrom(clazz)) {
                    log.warn("Class {} does not implement IController interface, skip", clazz.getName());
                    continue;
                }

                IController controller = (IController) ReflectUtil.newInstance(clazz);
                controllerMap.put(clazz.getName(), controller);
                log.info("Loaded controller: {}", controller.getName());
            } catch (Exception e) {
                log.error("Failed to load controller {}", clazz.getName(), e);
            }
        }
    }

    /**
     * 静态内部类实现单例模式，保证线程安全和懒加载
     */
    private static class SingletonHolder {
        private static final ControllerMgr INSTANCE = new ControllerMgr();
    }
}
